<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        h3 {
            padding: 20px 10px;
        }

        li {
            list-style: none;
        }

        .list li {
            line-height: 45px;
            text-indent: 10px;
            border: 1px solid #333;
        }

        .list li+li {
            border-top: 0;
        }

        .buttonGroup {
            margin-top: 20px;
        }

        .active {
            background-color: #6ff;
        }
    </style>
</head>

<body>
    <div class="wrap">
        <h3 id="title">批量操作元素</h3>
        <div class="list">
            <li>01</li>
            <li>02</li>
            <li>03</li>
            <li>04</li>
            <li>05</li>
            <li>06</li>
        </div>
    </div>
    <div class="buttonGroup">
        <button class="setHtml">
            设置html
        </button>
        <button class="getHtml">
            获取html
        </button>
        <button class="hide">隐藏</button>
        <button class="show">显示</button>
        <button class="setWidth">
            设置宽度
        </button>
        <button class="getWidth">
            获取宽度
        </button>
        <button class="setCss">css(设置)</button>
        <button class="getCss">css(获取)</button>
        <button class="attr">attr</button>
        <button class="prop">prop</button>
        <button class="addClass">addClass</button>
        <button class="removeClass">removeClass</button>
        <button class="eq">eq</button>
        <button class="siblings">siblings</button>
        <button class="chain">链式操作</button>
    </div>
</body>
<script>
    // 封装一个js库,可以帮助我们快速 操作元素
    // 批量操作元素  => 修改html,text,显隐,设置宽高,设置样式,类名(增删改),绑定事件



    function GetEle(selector) {
        this.eles = document.querySelectorAll(selector);
    }
    GetEle.prototype.html = function (con) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        if (arguments.length >= 1) { //有参数(至少一个)
            // for (var i = 0; i < this.eles.length; i++) {
            //     var ele = this.eles[i];
            //     ele.innerHTML = con;
            // }

            // this -> 调用此方法的实例化对象  -> 可以访问原型对象(prototype)所有的方法
            this.each(function (ele, index) {
                ele.innerHTML = con;
            })

        } else { //没有参数
            return this.eles[0].innerHTML;
        }
    }
    GetEle.prototype.text = function (con) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        if (arguments.length >= 1) { //有参数(至少一个)
            // for (var i = 0; i < this.eles.length; i++) {
            //     var ele = this.eles[i];
            //     ele.innerText = con;
            // }

            this.each(function (ele, index) {
                ele.innerText = con;
            })
        } else { //没有参数
            return this.eles[0].innerText;
        }
    }
    GetEle.prototype.val = function (con) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        if (arguments.length >= 1) { //有参数(至少一个)
            // for (var i = 0; i < this.eles.length; i++) {
            //     var ele = this.eles[i];
            //     ele.value = con;
            // }
            this.each(function (ele, index) {
                ele.value = con;
            })
        } else { //没有参数
            return this.eles[0].value;
        }
    }
    GetEle.prototype.hide = function () {
        // this -> 调用此方法的实例化对象  {eles:[]}
        // for (var i = 0; i < this.eles.length; i++) {
        //     var ele = this.eles[i];
        //     ele.style.display = "none";
        // }

        this.each(function (ele, index) {
            ele.style.display = "none";
        })

    }
    GetEle.prototype.show = function () {
        // this -> 调用此方法的实例化对象  {eles:[]}
        // for (var i = 0; i < this.eles.length; i++) {
        //     var ele = this.eles[i];
        //     ele.style.display = "block";
        // }

        this.each(function (ele, index) {
            ele.style.display = "block";
        })

    }
    GetEle.prototype.each = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        for (var i = 0; i < this.eles.length; i++) {
            var ele = this.eles[i];
            var index = i;

            //  注意  jquery中 fn(index,ele)  第一参数:下标  第二个:元素
            // fn(ele, index);   // this -> window

            fn.call(ele, ele, index);  // fn中的this指向循环当前的元素
        }

    }

    // on(eventType,callback)
    GetEle.prototype.on = function (eventType, fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        // for (var i = 0; i < this.eles.length; i++) {
        //     var ele = this.eles[i];
        //     var index = i;
        //     try {
        //         ele.addEventListener(eventType, fn);
        //     } catch (err) {
        //         ele.attachEvent("on" + eventType, fn);
        //     }
        // }
        this.each(function (ele) {
            try {
                ele.addEventListener(eventType, fn);
            } catch (err) {
                ele.attachEvent("on" + eventType, fn);
            }
        })
    }

    GetEle.prototype.off = function (eventType, fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}
        this.each(function (ele) {
            try {
                ele.removeEventListener(eventType, fn);
            } catch (err) {
                ele.detachEvent("on" + eventType, fn);
            }
        })
    }

    // click事件 是由on方法二次封装完成的  (可以给一个元素绑定多个事件)
    GetEle.prototype.click = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        this.on("click", fn);
    }
    GetEle.prototype.dblclick = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        this.on("dbclick", fn);
    }
    GetEle.prototype.mousedown = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        this.on("mousedown", fn);
    }
    GetEle.prototype.mouseup = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        this.on("mouseup", fn);
    }
    GetEle.prototype.mousemove = function (fn) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        this.on("mousemove", fn);
    }

    // width()  获取和设置 元素的宽度
    // width("200px")  有参数 => 设置
    // width()         没有参数 => 获取  


    GetEle.prototype.width = function (con) {
        // debugger;
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 1) {
            this.each(function (ele) {
                // con 可能有单位  也可能没有单位
                // 有单位(100px % pt em rem vw vh ) => 直接赋值
                // 没有单位(100) => 默认单位px

                var reg = /^\d+(px|%|pt|em|rem|vw|vh)$/
                if (reg.test(con)) { // 有单位
                    ele.style.width = con;
                } else {
                    ele.style.width = con + "px";
                }
            })
        } else {
            return parseInt(this.getStyle("width"));
            // return  this.eles[0].style.width; style只能获取内联样式
        }
    }

    GetEle.prototype.height = function (con) {
        // debugger;
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 1) {
            this.each(function (ele) {
                // con 可能有单位  也可能没有单位
                // 有单位(100px % pt em rem vw vh ) => 直接赋值
                // 没有单位(100) => 默认单位px

                var reg = /^\d+(px|%|pt|em|rem|vw|vh)$/
                if (reg.test(con)) { // 有单位
                    ele.style.height = con;
                } else {
                    ele.style.height = con + "px";
                }
            })
        } else {
            return parseInt(this.getStyle("height"));
            // return  this.eles[0].style.width; style只能获取内联样式
        }
    }

    // css()    获取和设置 元素的css演示
    // css("background","red")   有两个参数 => 设置
    // css("background")         一个参数 => 获取  

    GetEle.prototype.css = function (attr, val) {
        if (arguments.length >= 2) { // 有两个参数
            this.each(function (ele) {
                ele.style[attr] = val;
            })
        } else {
            // 一个参数   1. css("background")  2. css({background:"red"})
            if (attr.constructor === Object) {
                for (var key in attr) {
                    var val = attr[key];
                    this.css(key, val);
                }
            } else {
                return this.getStyle(attr);
            }
            // return this.eles[0].style[attr];
        }
    }



    GetEle.prototype.getStyle = function (attr) {
        // debugger;
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        var ele = this.eles[0];
        try {
            return window.getComputedStyle(ele)[attr];
        } catch (err) {
            return ele.currentStyle[attr];
        }
    }

    // attr()    获取和设置 html属性(属性节点)
    // attr("data-index","0")     有两个参数 => 设置
    // attr("data-index")         一个参数 => 获取  
    GetEle.prototype.attr = function (key, val) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 2) {
            this.each(function (ele) {
                ele.setAttribute(key, val);
            })
        } else {
            return this.eles[0].getAttribute(key);
        }
    }

    // prop()    获取和设置 元素节点的属性 ele.id
    // prop("id","demo")  有两个参数 => 设置
    // prop("id")         一个参数 => 获取  
    GetEle.prototype.prop = function (key, val) {
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 2) {
            this.each(function (ele) {
                ele[key] = val;
            })
        } else {
            return this.eles[0][key];
        }
    }

    // addClass()   向匹配的元素中新增一个或多个class名(多个class名用空格分隔 "one two three")
    GetEle.prototype.addClass = function (classCon) {
        // debugger;
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 1) {
            var list = classCon.split(/\s/g);
            this.each(function (ele) {
                ele.classList.add(...list);
            })
        }
    }

    // removeClass()   删除匹配的元素中一个或多个class名(多个class名用空格分隔)
    GetEle.prototype.removeClass = function (classCon) {
        // debugger;
        // this -> 调用此方法的实例化对象  {eles:[]}   -> 也可以访问原型对象(prototype)所有的方法
        if (arguments.length >= 1) {
            var list = classCon.split(/\s/g);
            this.each(function (ele) {
                ele.classList.remove(...list);
            })
        }
    }



    /* function getStyle(ele, attr) {
        try {
            return window.getComputedStyle(ele)[attr];
        } catch (err) {
            return ele.currentStyle[attr];
        }
    } */


    //  问题1: 每次操作元素 必须先得到实例化对象 在操作  => 麻烦
    //  解决方法 快速根据选择器得到实例化对象   => 对已有的构造函数进行二次封装

    function $(selector) {
        return new GetEle(selector);
    }
    // $.ajax   $函数的静态方法


    // $(".list li").on("click", function () {
    //     console.log(this);
    // })

    // $(".list li").click(function () {
    //     console.log(this);
    // })

    $(".setHtml").click(function () {
        $(".list li").html("hahahaha");
    })

    $(".setHtml").click(function () {
        alert(111111);
    })

    $(".setHtml").click(function () {
        alert($(".list li").html());
    })

    $(".hide").click(function () {
        $(".list li").hide();
    })

    $(".show").click(function () {
        $(".list li").show();
    })

    $(".setWidth").click(function () {
        // $(".list li").width("200px");
        $(".list li").width(200);
        $(".list li").height(200);
    })
    $(".getWidth").click(function () {
        alert($(".list li").width());;
        alert($(".list li").height());;
    })


    $(".setCss").click(function () {
        // $(".list li").width("200px");

        // 每次单独设置  太麻烦
        // $(".list li").css("background", "red");
        // $(".list li").css("width", "100px");
        // $(".list li").css("height", "100px");
        // $(".list li").css("text-align", "center");
        // $(".list li").css("line-height", "100px");

        // 传入一个对象作为参数  
        $(".list li").css({
            backgroundColor: "red",
            width: "100px",
            height: "100px",
            textAlign: "center",
            lineHeight: "100px",
        })
    })

    $(".getCss").click(function () {
        // $(".list li").width("200px");
        console.log($(".list li").css("backgroundColor"));
        console.log($(".list li").css("width"));
        console.log($(".list li").css("height"));
    })

    $(".attr").click(function () {
        $(".list li").attr("class", "active");
        $(".list li").attr("asd", "asd");   // 存在标签内
    })
    $(".prop").click(function () {
        $(".list li").prop("className", "active");
        $(".list li").prop("asd", "asd"); // 存在元素节点中 ele.asd
    })

    $(".addClass").click(function () {
        $(".list li").addClass("one two three");
    })

    $(".removeClass").click(function () {
        $(".list li").removeClass("one three");
    })




</script>

</html>